package cn.hff.concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author Holmofy
 */
public class ComputeThreadPoolTest {

    final static ThreadPoolExecutor computeExecutor;

    final static List<Callable<Long>> computeTasks;

    final static int task_num = 5000;

    static {
        computeExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
        computeTasks = new ArrayList<>(task_num);
        for (int i = 0; i < task_num; i++) {
            computeTasks.add(new LargeComputeTask());
        }
    }

    static class LargeComputeTask implements Callable<Long> {

        @Override
        public Long call() {
            long sum = 0;
            for (long i = 0; i < 50_0000; i++) {
                sum += i;
            }
            return sum;
        }
    }

    // 简单任务不如使用单线程执行
    static class TinyComputeTask implements Callable<Long> {

        @Override
        public Long call() {
            long sum = 0;
            for (long i = 0; i < 10; i++) {
                sum += i;
            }
            return sum;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 1; i <= Runtime.getRuntime().availableProcessors() * 8; i++) {
            computeExecutor.setCorePoolSize(i);
            computeExecutor.setMaximumPoolSize(i);
            computeExecutor.prestartAllCoreThreads();
            System.out.print(computeExecutor.getCorePoolSize());
            computeExecutor.invokeAll(computeTasks); //warm up all thread
            System.out.print("\t");
            testExecutor(computeExecutor, computeTasks);
            System.out.println();
            TimeUnit.SECONDS.sleep(5);// cpu rest
        }
        computeExecutor.shutdown();
    }

    private static <T> void testExecutor(ExecutorService executor, List<Callable<T>> tasks) throws InterruptedException {
        for (int i = 0; i < 8; i++) {
            long start = System.currentTimeMillis();
            executor.invokeAll(tasks); // ignore result
            long end = System.currentTimeMillis();
            System.out.print(end - start);
            System.out.print("\t");
            TimeUnit.SECONDS.sleep(1); // cpu rest
        }
    }

}
